package tomoto.util;

import tomoto.assertion.ParamUtil;

/**
 * Utility to perform vector operations on int array.
 * 
 * @author Tomoto Shimizu Washio
 * 
 */
public class IntVectorUtil {
	/** whether the parameter check is enabled */
	private static final boolean cs_paramCheckEnabled;
	static {
		cs_paramCheckEnabled = IntVectorUtil.class.desiredAssertionStatus();
	}

	@Deprecated
	private IntVectorUtil() {}

	/**
	 * Returns manhattan length of the vector.
	 * 
	 * @param v vector
	 * @return as described above
	 */
	public static int mabs(int[] v) {
		int result = 0;
		for (int i = 0; i < v.length; i++) {
			result += v[i];
		}
		return result;
	}

	/**
	 * Adds two vectors per each element and stores the result in the first
	 * vector.
	 * 
	 * @param v1 first vector
	 * @param v2 second vector
	 */
	public static void add(int[] v1, int[] v2) {
		if (cs_paramCheckEnabled) {
			ParamUtil.check(v1.length == v2.length);
		}
		for (int i = 0; i < v1.length; i++) {
			v1[i] += v2[i];
		}
	}

	/**
	 * Multiplies a vector by a scalar.
	 * 
	 * @param v vector of multiplicand
	 * @param x multiplier
	 */
	public static void mul(int[] v, int x) {
		for (int i = 0; i < v.length; i++) {
			v[i] *= x;
		}
	}

	/**
	 * Divides a vector by a scalar.
	 * 
	 * @param v vector of dividend
	 * @param x divisor
	 */
	public static void div(int[] v, int x) {
		for (int i = 0; i < v.length; i++) {
			v[i] /= x;
		}
	}

	/**
	 * Transforms a vector by multiplying by a scalar and adding a scalar
	 * offset.
	 * 
	 * @param v a vector to transform
	 * @param mul multiplier
	 * @param offset offset
	 */
	public static void trans(int[] v, int mul, int offset) {
		for (int i = 0; i < v.length; i++) {
			v[i] = v[i] * mul + offset;
		}
	}

	/**
	 * Performs logical AND operation on two vectors and stores the result in
	 * the first vector.
	 * 
	 * @param v1 first vector
	 * @param v2 second vector
	 */
	public static void logand(int[] v1, int v2) {
		for (int i = 0; i < v1.length; i++) {
			v1[i] &= v2;
		}
	}

	/**
	 * Returns the manhattan distance between the tip of two vectors.
	 * 
	 * @param v1 first vector
	 * @param v2 second vector
	 */
	public static int manhattanDistance(int[] v1, int[] v2) {
		if (cs_paramCheckEnabled) {
			ParamUtil.check(v1.length == v2.length);
		}
		int result = 0;
		for (int i = 0; i < v1.length; i++) {
			result += Math.abs(v2[i] - v1[i]);
		}
		return result;
	}
}
